/*
* Copyright 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.material.demo.utils;

import android.app.Activity;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.provider.Settings;
import android.support.annotation.NonNull;
import android.support.v7.app.AlertDialog;
import android.util.Log;
import android.util.SparseArray;

import static android.support.v4.app.ActivityCompat.requestPermissions;
import static com.material.demo.utils.PermissionUtils.PermissionHelper.verifyPermission;

/**
 * 权限管理工具类
 * 用于Android6.0权限检测判断
 *
 * @author WenJackp
 * @version 2.0
 */
public class PermissionUtils {

    private static SparseArray<OnPermissionHandlerListener> mPermissionListener = new SparseArray<>(0);

    private static final String TAG = PermissionUtils.class.getName();

    private Activity activity;
    private Builder mBuilder;
    private static PermissionUtils mInstance;
    private UIDialog mDialogIMPL;

    public static final int INVALIDE_REQUEST_CODE = -1;

    public static PermissionUtils createInstance(Activity activity) {
        if (mInstance == null) {
            mInstance = new PermissionUtils(activity);
        }
        return mInstance;
    }

    private PermissionUtils(Activity activity) {
        this.activity = activity;
        mBuilder = new Builder(new PermissionHelper(activity));
        logMsg("Init Compelete");
    }

    public PermissionUtils setDialogIMPL(UIDialog mDialogIMPL){
        this.mDialogIMPL = mDialogIMPL;
        return this;
    }

    public void request(String... permissions) {
        checkDialogIMPL();
        mBuilder
                .setListener(INVALIDE_REQUEST_CODE,new AutoPermissionHandlerListener(mBuilder,this.mDialogIMPL,null))
                .request(permissions);
    }

    public void request(int requestCode,OnPermissionHandlerListener mListener,String... permissions) {
        checkDialogIMPL();
        mBuilder
                .setListener(requestCode,new AutoPermissionHandlerListener(mBuilder,this.mDialogIMPL,mListener))
                .request(permissions);
    }

    private void checkDialogIMPL(){
        if(mDialogIMPL == null){
            //这里生成默认
            mDialogIMPL = new SimpleUIDialog();
        }
    }


    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {

        OnPermissionHandlerListener mListener = mPermissionListener.get(requestCode);
        logMsg("onRequestPermissionsResult : " + (mListener == null));

        if (mListener != null) {

            if (verifyPermission(grantResults)) {
                mListener.onPermissionRequested(requestCode);
            } else {

                boolean state = mBuilder.getHelper().shouldShowRequestPermissionRationale(permissions);

                if (state) {
                    mListener.onPermissionReject(requestCode, permissions);
                } else {
                    mListener.onPermissionRejectNever(requestCode);
                }
            }
        }
    }

    static class AutoPermissionHandlerListener implements OnPermissionHandlerListener, UIDialogHandler {

        private OnPermissionHandlerListener mListener;
        private UIDialog mDialogIMPL;
        private Activity activity;
        private Builder mBuilder;

        public AutoPermissionHandlerListener(Builder mBuilder, UIDialog mDialogIMPL, OnPermissionHandlerListener mListener) {
            this.mDialogIMPL = mDialogIMPL;
            this.mBuilder = mBuilder;
            this.mListener = mListener;
            this.activity = mBuilder.getActivity();
        }

        @Override
        public void onPermissionRequested(int requestCode) {
            if (mListener != null) {
                mListener.onPermissionRequested(requestCode);
            }
        }

        @Override
        public void onPermissionReject(final int requestCode, final String[] permissions) {

            logMsg("onPermissionReject");

            if (mDialogIMPL != null) {
                AlertDialog mDialog = mDialogIMPL.getDialog(activity, UIDialog.TYPE_REJECT, this);
                mDialog.show();
            }

            if (mListener != null) {
                mListener.onPermissionReject(requestCode, permissions);
            }
        }

        @Override
        public void onPermissionRejectNever(int requestCode) {

            logMsg("onPermissionRejectNever");

            if (mDialogIMPL != null) {
                AlertDialog mDialog = mDialogIMPL.getDialog(activity, UIDialog.TYPE_NEVER_REJECT, this);
                mDialog.show();
            }

            if (mListener != null) {
                mListener.onPermissionRejectNever(requestCode);
            }
        }

        @Override
        public void request() {
            this.mBuilder.retry();
        }

        @Override
        public void setting() {
            Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
                    Uri.fromParts("package", activity.getPackageName(), null));
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            activity.startActivity(intent);
        }

        @Override
        public void cancel() {

        }
    }

    public class Builder {

        private int requestCode;
        private OnPermissionHandlerListener mListener;

        private Activity activity;
        private PermissionHelper mPermissionHelper;
        private String[] permissions;

        public Builder(PermissionHelper mHelper) {
            this.mPermissionHelper = mHelper;
            this.activity = mHelper.getActivity();
        }

        public Activity getActivity(){
            return this.activity;
        }

        public PermissionHelper getHelper(){
            return mPermissionHelper;
        }

        public void request(String... permissions) {

            this.permissions = permissions;

            mPermissionListener.put(requestCode,mListener);

            if (activity != null) {
                if (mPermissionHelper.checkSelfPermission(permissions)) {
                    //申请权限
                    if (mPermissionHelper.shouldShowRequestPermissionRationale(permissions)) {
                        if (mListener != null) {
                            mListener.onPermissionReject(requestCode, permissions);
                        }
                    } else {
                        requestPermissions(activity, permissions,
                                requestCode);
                    }
                } else {
                    if (mListener != null) {
                        mListener.onPermissionRequested(requestCode);
                    }
                }
            }
        }

        private void retry(){
            request(permissions);
        }

        public Builder setListener(int requestCode,OnPermissionHandlerListener mListener) {
            this.requestCode = requestCode;
            this.mListener = mListener;
            mPermissionListener.put(requestCode,mListener);
            return this;
        }
    }

    public interface OnPermissionHandlerListener {

        void onPermissionRequested(int requestCode);

        void onPermissionReject(int requestCode, String[] permissions);

        void onPermissionRejectNever(int requestCode);
    }

    public static class PermissionHelper {

        private Activity activity;

        public PermissionHelper(Activity activity) {
            this.activity = activity;
        }

        public Activity getActivity() {
            return this.activity;
        }

        /**
         * 判断权限是否已经注册
         *
         * @param permissions 多个权限
         * @return true没注册
         */
        public boolean checkSelfPermission(String[] permissions) {

            if (permissions != null && permissions.length > 0) {
                for (String permission : permissions) {
                    boolean self = android.support.v4.content.ContextCompat.checkSelfPermission(activity, permission) != PackageManager.PERMISSION_GRANTED;
                    if (self) {
                        return true;
                    }
                }
            }
            return false;
        }

        /**
         * 判断权限是否已经注册
         *
         * @param permission 单个权限
         * @return true没注册
         */
        public boolean checkSelfPermission(String permission) {
            return android.support.v4.app.ActivityCompat.checkSelfPermission(activity, permission) != PackageManager.PERMISSION_GRANTED;
        }

        public boolean shouldShowRequestPermissionRationale(String[] permissions) {

            if (permissions != null && permissions.length > 0) {
                for (String permission : permissions) {
                    boolean self = shouldShowRequestPermissionRationale(permission);
                    if (self) {
                        return true;
                    }
                }
            }
            return false;
        }

        public boolean shouldShowRequestPermissionRationale(String permission) {
            return android.support.v4.app.ActivityCompat.shouldShowRequestPermissionRationale(activity, permission);
        }

        private void requestPermissions(String[] permissions, int requestCode) {
            android.support.v4.app.ActivityCompat
                    .requestPermissions(activity, permissions,
                            requestCode);
        }

        /**
         * 校验权限状态
         *
         * @param grantResults 权限状态集合
         * @return true全部已经注册
         */
        public static boolean verifyPermission(int[] grantResults) {
            // At least one result must be checked.
            if (grantResults.length < 1) {
                return false;
            }

            // Verify that each required permission has been granted, otherwise return false.
            for (int result : grantResults) {
                if (result != PackageManager.PERMISSION_GRANTED) {
                    return false;
                }
            }
            return true;
        }
    }

    private static void logMsg(String msg) {
        Log.e(TAG, msg);
    }

    public interface UIDialog {

        int TYPE_REJECT = 0;
        int TYPE_NEVER_REJECT = 1;

        AlertDialog getDialog(Context context, int type, UIDialogHandler mHandler);
    }

    public interface UIDialogHandler {
        void request();

        void cancel();

        void setting();
    }

    class SimpleUIDialog implements UIDialog{

        @Override
        public AlertDialog getDialog(Context context, int type, final UIDialogHandler mHandler) {

            final AlertDialog.Builder mBuilder = new AlertDialog.Builder(context);

            if(type == TYPE_REJECT){
                mBuilder.setTitle("权限设置")
                        .setMessage("你需要打开权限")
                        .setNegativeButton("ok", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                dialog.dismiss();
                                mHandler.request();
                            }
                        })
                        .setPositiveButton("cancel", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                dialog.dismiss();
                                mHandler.cancel();
                            }
                        });
            }else if(type == TYPE_NEVER_REJECT){
                mBuilder.setTitle("权限设置2")
                        .setMessage("你需要打开权限2")
                        .setNegativeButton("ok2", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                dialog.dismiss();
                                mHandler.setting();
                            }
                        })
                        .setPositiveButton("cancel2", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                dialog.dismiss();
                                mHandler.cancel();
                            }
                        });
            }

            return mBuilder.create();
        }
    }
}
